<?php

/**
 *		//IP转换类//
 *		//这是一份试验品，由大街编写（zhongmingzi@gmail.com）
 *		//本程序默认环境：Zend Optimizer Yes / 3.3.3
 *		//		Apache/2.0.63 (Win32) PHP/5.2.12
 *		//		MySQL 支持 Yes / client lib version 5.0.89
 *		//		GD library Yes / bundled (2.0.34 compatible)
 *		//		eAccelerator/Memcache/xcache Yes
 *		//		cURL support enabled
 *		//时间：2011 3 23 08:45:23//
 */
if(!defined('IN')) {
	exit('Access Denied');
}

define("GEOIP_COUNTRY_BEGIN", 16776960);
define("GEOIP_STATE_BEGIN_REV0", 16700000);
define("GEOIP_STATE_BEGIN_REV1", 16000000);
define("GEOIP_STANDARD", 0);
define("GEOIP_MEMORY_CACHE", 1);
define("GEOIP_SHARED_MEMORY", 2);
define("STRUCTURE_INFO_MAX_SIZE", 20);
define("DATABASE_INFO_MAX_SIZE", 100);
define("GEOIP_COUNTRY_EDITION", 106);
define("GEOIP_PROXY_EDITION", 8);
define("GEOIP_ASNUM_EDITION", 9);
define("GEOIP_NETSPEED_EDITION", 10);
define("GEOIP_REGION_EDITION_REV0", 112);
define("GEOIP_REGION_EDITION_REV1", 3);
define("GEOIP_CITY_EDITION_REV0", 111);
define("GEOIP_CITY_EDITION_REV1", 2);
define("GEOIP_ORG_EDITION", 110);
define("GEOIP_ISP_EDITION", 4);
define("SEGMENT_RECORD_LENGTH", 3);
define("STANDARD_RECORD_LENGTH", 3);
define("ORG_RECORD_LENGTH", 4);
define("MAX_RECORD_LENGTH", 4);
define("MAX_ORG_RECORD_LENGTH", 300);
define("GEOIP_SHM_KEY", 0x4f415401);
define("US_OFFSET", 1);
define("CANADA_OFFSET", 677);
define("WORLD_OFFSET", 1353);
define("FIPS_RANGE", 360);
define("GEOIP_UNKNOWN_SPEED", 0);
define("GEOIP_DIALUP_SPEED", 1);
define("GEOIP_CABLEDSL_SPEED", 2);
define("GEOIP_CORPORATE_SPEED", 3);
define("GEOIP_DOMAIN_EDITION", 11);
define("GEOIP_LOCATIONA_EDITION", 13);
define("GEOIP_ACCURACYRADIUS_EDITION", 14);
define("GEOIP_CITYCOMBINED_EDITION", 15);
define("CITYCOMBINED_FIXED_RECORD", 7 );

class ip {
	var $ip;

	var $country_code;//国家代码，如CN
	var $country_code3;//国家代码3位，如CHN
	var $country_name;//国家全称，如china
	var $country_cnname;//国家中文，如中国
	var $region;
	var $region_name;//
	var $city;//城市英文名称
	var $postal_code;//邮政编号
	var $latitude;//维度
	var $longitude;//经度
	var $area_code;
	var $metro_code;
	var $continent_code;
	var $timezone;//时区
	var $flag;//国旗

	var $fullcz;
	var $cnisp;
	var $cncity;
	var $cnpro;
	var $errno = 0;

	const GEO = "./static/ipdata/GeoLiteCity.dat";
	const CZ = "./static/ipdata/QQWry.Dat";
	
	function ip($ip) {
		if(preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
			$iparray = explode('.', $ip);
			if($iparray[0] == 10 || $iparray[0] == 127 || ($iparray[0] == 192 && $iparray[1] == 168) || ($iparray[0] == 172 && ($iparray[1] >= 16 && $iparray[1] <= 31))) {
				$this->ip = $ip;
				$this->invalid_ip('局域网');
			} elseif($iparray[0] > 255 || $iparray[1] > 255 || $iparray[2] > 255 || $iparray[3] > 255) {
				$this->error('-11');
			} else $this->ip = $ip;
		} else {
			$this->error('-11');//无效IP地址
		}
	}
	
	function invalid_ip($type) {
		$this->code = 'CN';
		$this->cncity = $type;
		$this->error('-12');//特殊IP地址
	}
	
	function _geo() {
		if(!$this->ip) return false;
		else $ip = $this->ip;
		$gi = geoip_open(ROOT.self::GEO, GEOIP_STANDARD);
		$record = geoip_record_by_addr($gi, $ip);

		$this->country_code = $record->country_code;
		$this->country_code3 = $record->country_code3;
		$this->country_name = $record->country_name;
		$this->region = $record->region;
		$this->region_name = $GEOIP_REGION_NAME[$this->country_code][$this->region];
		$this->city = $record->city;
		$this->postal_code = $record->postal_code;
		$this->latitude = $record->latitude;
		$this->longitude = $record->longitude;
		$this->metro_code = $record->metro_code;
		$this->area_code = $record->area_code;

		require_once libfile('geo/timezone', 'include');
		$this->timezone = get_time_zone($this->country_code, $this->region);
		require_once libfile('geo/country2cn', 'include');
		$up_code = strtoupper($this->country_code);
		$this->country_cnname = $up_code && isset($lang[$up_code]) ? $lang[$up_code] : '';
		$this->flag = self::code2flag($this->country_code, $this->country_cnname);
		geoip_close($gi);
	}
	
	function get($nocn = false) {
		if($this->errno < 0) return false;
		$this->_geo();
		if($this->country_code == 'CN' && $nocn == false) $this->cn();
		$return = array(
			'country_code' => $this->country_code,
			'country_code3' => $this->country_code3,
			'country_name' => $this->country_name,
			'country_cnname' => $this->country_cnname,
			'region' => $this->region,
			'region_name' => $this->region_name,
			'city' => $this->city,
			'postal_code' => $this->postal_code,
			'latitude' => $this->latitude,
			'longitude' => $this->longitude,
			'area_code' => $this->area_code,
			'metro_code' => $this->metro_code,
			'continent_code' => $this->continent_code,
			'timezone' => $this->timezone,
			'flag' => $this->flag,
			'fullcz' => $this->fullcz,
			'cnisp' => $this->cnisp,
			'cncity' => $this->cncity,
			'cnpro' => $this->cnpro,
			'errno' =>  $this->errno
		);
		return $return;
	}

	static function code2flag($code, $codename = '') {
		if(empty($code)) return '';
		if(empty($codename)) {
			require_once libfile('geo/country2cn', 'include');
			$up_code = strtoupper($code);
			$codename = $up_code && isset($lang[$up_code]) ? $lang[$up_code] : '';
		}
		return "<img src=\"".URL."/static/image/country/".strtolower($code).".jpg\" title=\"{$codename}\" alt=\"{$codename}\" />";
	}

	function cn() {
		if($this->errno < 0) return false;
		$this->_cz();
		$this->_cz_explode();
	}

	function _cz_explode($str = '') {
		if($str == '' && $this->fullcz != '') $str = $this->fullcz;
		else return -10;//传来无效参数
		$area = explode(" ",$str);
		$this->cnisp = trim($area[1]);
		$zxs = array(
			   "/^(北京).*/",
			   "/^(天津).*/",
			   "/^(上海).*/",
			   "/^(重庆).*/"
			   );
		$zxsr = array(
			   "北京市",
			   "天津市",
			   "上海市",
			   "重庆市"
			   );
		$zzq = array(
			   "/^(广西)(.*)/",
			   "/^(内蒙古)(.*)/",
			   "/^(西藏)(.*)/",
			   "/^(宁夏)(.*)/",
			   "/^(新疆)(.*)/"
			   );
		$zzqr = array(
			   "广西壮族自治区",
			   "内蒙古自治区",
			   "西藏自治区",
			   "宁夏回族自治区",
			   "新疆维吾尔自治区"
			   );
		if(preg_match("/^(北京|天津|上海|重庆)/", $area[0])) {
			$this->cncity = $this->cnpro = preg_replace($zxs, $zxsr, $area[0]);
		} elseif(preg_match("/^(广西|内蒙古|西藏|宁夏|新疆)/",$area[0])) {
			$this->cnpro = preg_replace($zzq, $zzqr, $area[0]);
			$ci_name = preg_replace($zzq, '$2', $area[0]);
			if($ci_name == '') {
				$this->cncity = $this->cnpro;
			} else {
				if(preg_match("/(市|盟|州|地区)$/", $ci_name)) {
					$this->cncity = $ci_name;
				} elseif(preg_match("/(市|盟|州|地区)(.+)$/", $ci_name)) {
					$this->cncity = preg_replace("/(.+?市|.+?盟|.+?州|.+?地区)(.+)$/", '$1', $ci_name);
				} else {
					$this->cncity = $this->cnpro;
				}
			}
		} else {
			if(preg_match("/省$/", $area[0])) {
				$this->cncity = $this->cnpro = preg_replace("/^(.+省)/",'$1', $area[0]);
			} elseif(preg_match("/^(.+省)(.+)$/", $area[0])) {
				$this->cnpro = preg_replace("/^(.+省)(.+)$/", '$1', $area[0]);
				$this->cncity = preg_replace("/^(.+省)(.+?市|.+?地区|.+?州)(.*县?|.*区?|.*市?|.*)(.*)/", '$2', $area[0]);
			} else {
				$this->cncity = $this->cnpro = $area[0];
			}
		
		}
		return true;
	}

	function _cz() {
		if(!$this->ip) return false;
		else $ip = $this->ip;
		$ipdatafile = ROOT.self::CZ;
		if(!$fd = @fopen($ipdatafile, 'rb')) {
			return -100;//文件不存在
		}

		$ip = explode('.', $ip);
		$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];

		if(!($DataBegin = fread($fd, 4)) || !($DataEnd = fread($fd, 4)) ) return;
		@$ipbegin = implode('', unpack('L', $DataBegin));
		if($ipbegin < 0) $ipbegin += pow(2, 32);
		@$ipend = implode('', unpack('L', $DataEnd));
		if($ipend < 0) $ipend += pow(2, 32);
		$ipAllNum = ($ipend - $ipbegin) / 7 + 1;

		$BeginNum = $ip2num = $ip1num = 0;
		$ipAddr1 = $ipAddr2 = '';
		$EndNum = $ipAllNum;

		while($ip1num > $ipNum || $ip2num < $ipNum) {
			$Middle= intval(($EndNum + $BeginNum) / 2);

			fseek($fd, $ipbegin + 7 * $Middle);
			$ipData1 = fread($fd, 4);
			if(strlen($ipData1) < 4) {
				fclose($fd);
				return -1;
			}
			$ip1num = implode('', unpack('L', $ipData1));
			if($ip1num < 0) $ip1num += pow(2, 32);

			if($ip1num > $ipNum) {
				$EndNum = $Middle;
				continue;
			}

			$DataSeek = fread($fd, 3);
			if(strlen($DataSeek) < 3) {
				fclose($fd);
				return -2;
			}
			$DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
			fseek($fd, $DataSeek);
			$ipData2 = fread($fd, 4);
			if(strlen($ipData2) < 4) {
				fclose($fd);
				return -3;
			}
			$ip2num = implode('', unpack('L', $ipData2));
			if($ip2num < 0) $ip2num += pow(2, 32);

			if($ip2num < $ipNum) {
				if($Middle == $BeginNum) {
					fclose($fd);
					return -4;
				}
				$BeginNum = $Middle;
			}
		}

		$ipFlag = fread($fd, 1);
		if($ipFlag == chr(1)) {
			$ipSeek = fread($fd, 3);
			if(strlen($ipSeek) < 3) {
				fclose($fd);
				return -5;
			}
			$ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
			fseek($fd, $ipSeek);
			$ipFlag = fread($fd, 1);
		}

		if($ipFlag == chr(2)) {
			$AddrSeek = fread($fd, 3);
			if(strlen($AddrSeek) < 3) {
				fclose($fd);
				return -6;
			}
			$ipFlag = fread($fd, 1);
			if($ipFlag == chr(2)) {
				$AddrSeek2 = fread($fd, 3);
				if(strlen($AddrSeek2) < 3) {
					fclose($fd);
					return -7;
				}
				$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
				fseek($fd, $AddrSeek2);
			} else {
				fseek($fd, -1, SEEK_CUR);
			}

			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr2 .= $char;

			$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
			fseek($fd, $AddrSeek);

			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr1 .= $char;
		} else {
			fseek($fd, -1, SEEK_CUR);
			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr1 .= $char;

			$ipFlag = fread($fd, 1);
			if($ipFlag == chr(2)) {
				$AddrSeek2 = fread($fd, 3);
				if(strlen($AddrSeek2) < 3) {
					fclose($fd);
					return -8;
				}
				$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
				fseek($fd, $AddrSeek2);
			} else {
				fseek($fd, -1, SEEK_CUR);
			}
			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr2 .= $char;
		}
		fclose($fd);

		if(preg_match('/http/i', $ipAddr2)) {
			$ipAddr2 = '';
		}
		$ipaddr = "$ipAddr1 $ipAddr2";
		$ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
		$ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
		$ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
		if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
			$ipaddr = -9;
		}

		return $this->fullcz = diconv($ipaddr, 'GBK');
	}
	
	function error($code) {
		$this->errno = $code;
	}
}

class GeoIP {
	var $flags;
	var $filehandle;
	var $memory_buffer;
	var $databaseType;
	var $databaseSegments;
	var $record_length;
	var $shmid;
	var $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
"" => 0, "AP" => 1, "EU" => 2, "AD" => 3, "AE" => 4, "AF" => 5, 
"AG" => 6, "AI" => 7, "AL" => 8, "AM" => 9, "AN" => 10, "AO" => 11, 
"AQ" => 12, "AR" => 13, "AS" => 14, "AT" => 15, "AU" => 16, "AW" => 17, 
"AZ" => 18, "BA" => 19, "BB" => 20, "BD" => 21, "BE" => 22, "BF" => 23, 
"BG" => 24, "BH" => 25, "BI" => 26, "BJ" => 27, "BM" => 28, "BN" => 29, 
"BO" => 30, "BR" => 31, "BS" => 32, "BT" => 33, "BV" => 34, "BW" => 35, 
"BY" => 36, "BZ" => 37, "CA" => 38, "CC" => 39, "CD" => 40, "CF" => 41, 
"CG" => 42, "CH" => 43, "CI" => 44, "CK" => 45, "CL" => 46, "CM" => 47, 
"CN" => 48, "CO" => 49, "CR" => 50, "CU" => 51, "CV" => 52, "CX" => 53, 
"CY" => 54, "CZ" => 55, "DE" => 56, "DJ" => 57, "DK" => 58, "DM" => 59, 
"DO" => 60, "DZ" => 61, "EC" => 62, "EE" => 63, "EG" => 64, "EH" => 65, 
"ER" => 66, "ES" => 67, "ET" => 68, "FI" => 69, "FJ" => 70, "FK" => 71, 
"FM" => 72, "FO" => 73, "FR" => 74, "FX" => 75, "GA" => 76, "GB" => 77,
"GD" => 78, "GE" => 79, "GF" => 80, "GH" => 81, "GI" => 82, "GL" => 83, 
"GM" => 84, "GN" => 85, "GP" => 86, "GQ" => 87, "GR" => 88, "GS" => 89, 
"GT" => 90, "GU" => 91, "GW" => 92, "GY" => 93, "HK" => 94, "HM" => 95, 
"HN" => 96, "HR" => 97, "HT" => 98, "HU" => 99, "ID" => 100, "IE" => 101, 
"IL" => 102, "IN" => 103, "IO" => 104, "IQ" => 105, "IR" => 106, "IS" => 107, 
"IT" => 108, "JM" => 109, "JO" => 110, "JP" => 111, "KE" => 112, "KG" => 113, 
"KH" => 114, "KI" => 115, "KM" => 116, "KN" => 117, "KP" => 118, "KR" => 119, 
"KW" => 120, "KY" => 121, "KZ" => 122, "LA" => 123, "LB" => 124, "LC" => 125, 
"LI" => 126, "LK" => 127, "LR" => 128, "LS" => 129, "LT" => 130, "LU" => 131, 
"LV" => 132, "LY" => 133, "MA" => 134, "MC" => 135, "MD" => 136, "MG" => 137, 
"MH" => 138, "MK" => 139, "ML" => 140, "MM" => 141, "MN" => 142, "MO" => 143, 
"MP" => 144, "MQ" => 145, "MR" => 146, "MS" => 147, "MT" => 148, "MU" => 149, 
"MV" => 150, "MW" => 151, "MX" => 152, "MY" => 153, "MZ" => 154, "NA" => 155,
"NC" => 156, "NE" => 157, "NF" => 158, "NG" => 159, "NI" => 160, "NL" => 161, 
"NO" => 162, "NP" => 163, "NR" => 164, "NU" => 165, "NZ" => 166, "OM" => 167, 
"PA" => 168, "PE" => 169, "PF" => 170, "PG" => 171, "PH" => 172, "PK" => 173, 
"PL" => 174, "PM" => 175, "PN" => 176, "PR" => 177, "PS" => 178, "PT" => 179, 
"PW" => 180, "PY" => 181, "QA" => 182, "RE" => 183, "RO" => 184, "RU" => 185, 
"RW" => 186, "SA" => 187, "SB" => 188, "SC" => 189, "SD" => 190, "SE" => 191, 
"SG" => 192, "SH" => 193, "SI" => 194, "SJ" => 195, "SK" => 196, "SL" => 197, 
"SM" => 198, "SN" => 199, "SO" => 200, "SR" => 201, "ST" => 202, "SV" => 203, 
"SY" => 204, "SZ" => 205, "TC" => 206, "TD" => 207, "TF" => 208, "TG" => 209, 
"TH" => 210, "TJ" => 211, "TK" => 212, "TM" => 213, "TN" => 214, "TO" => 215, 
"TL" => 216, "TR" => 217, "TT" => 218, "TV" => 219, "TW" => 220, "TZ" => 221, 
"UA" => 222, "UG" => 223, "UM" => 224, "US" => 225, "UY" => 226, "UZ" => 227, 
"VA" => 228, "VC" => 229, "VE" => 230, "VG" => 231, "VI" => 232, "VN" => 233,
"VU" => 234, "WF" => 235, "WS" => 236, "YE" => 237, "YT" => 238, "RS" => 239, 
"ZA" => 240, "ZM" => 241, "ME" => 242, "ZW" => 243, "A1" => 244, "A2" => 245, 
"O1" => 246, "AX" => 247, "GG" => 248, "IM" => 249, "JE" => 250, "BL" => 251,
"MF" => 252
);
	var $GEOIP_COUNTRY_CODES = array(
"", "AP", "EU", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ",
"AR", "AS", "AT", "AU", "AW", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH",
"BI", "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA",
"CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU",
"CV", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG",
"EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "FX", "GA", "GB",
"GD", "GE", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT",
"GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IN",
"IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM",
"KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS",
"LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "MH", "MK", "ML", "MM", "MN",
"MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA",
"NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA",
"PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY",
"QA", "RE", "RO", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI",
"SJ", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TC", "TD",
"TF", "TG", "TH", "TJ", "TK", "TM", "TN", "TO", "TL", "TR", "TT", "TV", "TW",
"TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN",
"VU", "WF", "WS", "YE", "YT", "RS", "ZA", "ZM", "ME", "ZW", "A1", "A2", "O1",
"AX", "GG", "IM", "JE", "BL", "MF"
);
	var $GEOIP_COUNTRY_CODES3 = array(
"","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT","AGO","ATA","ARG",
"ASM","AUT","AUS","ABW","AZE","BIH","BRB","BGD","BEL","BFA","BGR","BHR","BDI",
"BEN","BMU","BRN","BOL","BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK",
"COD","CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI","CUB","CPV",
"CXR","CYP","CZE","DEU","DJI","DNK","DMA","DOM","DZA","ECU","EST","EGY","ESH",
"ERI","ESP","ETH","FIN","FJI","FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD",
"GEO","GUF","GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","SGS","GTM","GUM",
"GNB","GUY","HKG","HMD","HND","HRV","HTI","HUN","IDN","IRL","ISR","IND","IOT",
"IRQ","IRN","ISL","ITA","JAM","JOR","JPN","KEN","KGZ","KHM","KIR","COM","KNA",
"PRK","KOR","KWT","CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
"LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI","MMR","MNG","MAC",
"MNP","MTQ","MRT","MSR","MLT","MUS","MDV","MWI","MEX","MYS","MOZ","NAM","NCL",
"NER","NFK","NGA","NIC","NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER",
"PYF","PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW","PRY","QAT",
"REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN","SWE","SGP","SHN","SVN","SJM",
"SVK","SLE","SMR","SEN","SOM","SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF",
"TGO","THA","TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN","TZA",
"UKR","UGA","UMI","USA","URY","UZB","VAT","VCT","VEN","VGB","VIR","VNM","VUT",
"WLF","WSM","YEM","MYT","SRB","ZAF","ZMB","MNE","ZWE","A1","A2","O1",
"ALA","GGY","IMN","JEY","BLM","MAF"
	);
	var $GEOIP_COUNTRY_NAMES = array(
"", "Asia/Pacific Region", "Europe", "Andorra", "United Arab Emirates",
"Afghanistan", "Antigua and Barbuda", "Anguilla", "Albania", "Armenia",
"Netherlands Antilles", "Angola", "Antarctica", "Argentina", "American Samoa",
"Austria", "Australia", "Aruba", "Azerbaijan", "Bosnia and Herzegovina",
"Barbados", "Bangladesh", "Belgium", "Burkina Faso", "Bulgaria", "Bahrain",
"Burundi", "Benin", "Bermuda", "Brunei Darussalam", "Bolivia", "Brazil",
"Bahamas", "Bhutan", "Bouvet Island", "Botswana", "Belarus", "Belize",
"Canada", "Cocos (Keeling) Islands", "Congo, The Democratic Republic of the",
"Central African Republic", "Congo", "Switzerland", "Cote D'Ivoire", "Cook Islands",
"Chile", "Cameroon", "China", "Colombia", "Costa Rica", "Cuba", "Cape Verde",
"Christmas Island", "Cyprus", "Czech Republic", "Germany", "Djibouti",
"Denmark", "Dominica", "Dominican Republic", "Algeria", "Ecuador", "Estonia",
"Egypt", "Western Sahara", "Eritrea", "Spain", "Ethiopia", "Finland", "Fiji",
"Falkland Islands (Malvinas)", "Micronesia, Federated States of", "Faroe Islands",
"France", "France, Metropolitan", "Gabon", "United Kingdom",
"Grenada", "Georgia", "French Guiana", "Ghana", "Gibraltar", "Greenland",
"Gambia", "Guinea", "Guadeloupe", "Equatorial Guinea", "Greece", "South Georgia and the South Sandwich Islands",
"Guatemala", "Guam", "Guinea-Bissau",
"Guyana", "Hong Kong", "Heard Island and McDonald Islands", "Honduras",
"Croatia", "Haiti", "Hungary", "Indonesia", "Ireland", "Israel", "India",
"British Indian Ocean Territory", "Iraq", "Iran, Islamic Republic of",
"Iceland", "Italy", "Jamaica", "Jordan", "Japan", "Kenya", "Kyrgyzstan",
"Cambodia", "Kiribati", "Comoros", "Saint Kitts and Nevis", "Korea, Democratic People's Republic of",
"Korea, Republic of", "Kuwait", "Cayman Islands",
"Kazakhstan", "Lao People's Democratic Republic", "Lebanon", "Saint Lucia",
"Liechtenstein", "Sri Lanka", "Liberia", "Lesotho", "Lithuania", "Luxembourg",
"Latvia", "Libyan Arab Jamahiriya", "Morocco", "Monaco", "Moldova, Republic of",
"Madagascar", "Marshall Islands", "Macedonia",
"Mali", "Myanmar", "Mongolia", "Macau", "Northern Mariana Islands",
"Martinique", "Mauritania", "Montserrat", "Malta", "Mauritius", "Maldives",
"Malawi", "Mexico", "Malaysia", "Mozambique", "Namibia", "New Caledonia",
"Niger", "Norfolk Island", "Nigeria", "Nicaragua", "Netherlands", "Norway",
"Nepal", "Nauru", "Niue", "New Zealand", "Oman", "Panama", "Peru", "French Polynesia",
"Papua New Guinea", "Philippines", "Pakistan", "Poland", "Saint Pierre and Miquelon",
"Pitcairn Islands", "Puerto Rico", "Palestinian Territory",
"Portugal", "Palau", "Paraguay", "Qatar", "Reunion", "Romania",
"Russian Federation", "Rwanda", "Saudi Arabia", "Solomon Islands",
"Seychelles", "Sudan", "Sweden", "Singapore", "Saint Helena", "Slovenia",
"Svalbard and Jan Mayen", "Slovakia", "Sierra Leone", "San Marino", "Senegal",
"Somalia", "Suriname", "Sao Tome and Principe", "El Salvador", "Syrian Arab Republic",
"Swaziland", "Turks and Caicos Islands", "Chad", "French Southern Territories",
"Togo", "Thailand", "Tajikistan", "Tokelau", "Turkmenistan",
"Tunisia", "Tonga", "Timor-Leste", "Turkey", "Trinidad and Tobago", "Tuvalu",
"Taiwan", "Tanzania, United Republic of", "Ukraine",
"Uganda", "United States Minor Outlying Islands", "United States", "Uruguay",
"Uzbekistan", "Holy See (Vatican City State)", "Saint Vincent and the Grenadines",
"Venezuela", "Virgin Islands, British", "Virgin Islands, U.S.",
"Vietnam", "Vanuatu", "Wallis and Futuna", "Samoa", "Yemen", "Mayotte",
"Serbia", "South Africa", "Zambia", "Montenegro", "Zimbabwe",
"Anonymous Proxy","Satellite Provider","Other",
"Aland Islands","Guernsey","Isle of Man","Jersey","Saint Barthelemy","Saint Martin"
);

	var $GEOIP_CONTINENT_CODES = array(
  "--", "AS", "EU", "EU", "AS", "AS", "NA", "NA", "EU", "AS", 
  "NA", "AF", "AN", "SA", "OC", "EU", "OC", "NA", "AS", "EU", 
  "NA", "AS", "EU", "AF", "EU", "AS", "AF", "AF", "NA", "AS", 
  "SA", "SA", "NA", "AS", "AN", "AF", "EU", "NA", "NA", "AS", 
  "AF", "AF", "AF", "EU", "AF", "OC", "SA", "AF", "AS", "SA", 
  "NA", "NA", "AF", "AS", "AS", "EU", "EU", "AF", "EU", "NA", 
  "NA", "AF", "SA", "EU", "AF", "AF", "AF", "EU", "AF", "EU", 
  "OC", "SA", "OC", "EU", "EU", "EU", "AF", "EU", "NA", "AS", 
  "SA", "AF", "EU", "NA", "AF", "AF", "NA", "AF", "EU", "AN", 
  "NA", "OC", "AF", "SA", "AS", "AN", "NA", "EU", "NA", "EU", 
  "AS", "EU", "AS", "AS", "AS", "AS", "AS", "EU", "EU", "NA", 
  "AS", "AS", "AF", "AS", "AS", "OC", "AF", "NA", "AS", "AS", 
  "AS", "NA", "AS", "AS", "AS", "NA", "EU", "AS", "AF", "AF", 
  "EU", "EU", "EU", "AF", "AF", "EU", "EU", "AF", "OC", "EU", 
  "AF", "AS", "AS", "AS", "OC", "NA", "AF", "NA", "EU", "AF", 
  "AS", "AF", "NA", "AS", "AF", "AF", "OC", "AF", "OC", "AF", 
  "NA", "EU", "EU", "AS", "OC", "OC", "OC", "AS", "NA", "SA", 
  "OC", "OC", "AS", "AS", "EU", "NA", "OC", "NA", "AS", "EU", 
  "OC", "SA", "AS", "AF", "EU", "EU", "AF", "AS", "OC", "AF", 
  "AF", "EU", "AS", "AF", "EU", "EU", "EU", "AF", "EU", "AF", 
  "AF", "SA", "AF", "NA", "AS", "AF", "NA", "AF", "AN", "AF", 
  "AS", "AS", "OC", "AS", "AF", "OC", "AS", "EU", "NA", "OC", 
  "AS", "AF", "EU", "AF", "OC", "NA", "SA", "AS", "EU", "NA", 
  "SA", "NA", "NA", "AS", "OC", "OC", "OC", "AS", "AF", "EU", 
  "AF", "AF", "EU", "AF", "--", "--", "--", "EU", "EU", "EU", 
  "EU", "NA", "NA"
);
	
}

function geoip_load_shared_mem ($file) {

	$fp = fopen($file, "rb");
	if (!$fp) {
		print "error opening $file: $php_errormsg\n";
		exit;
	}
	$s_array = fstat($fp);
	$size = $s_array['size'];
	if ($shmid = @shmop_open (GEOIP_SHM_KEY, "w", 0, 0)) {
		shmop_delete ($shmid);
		shmop_close ($shmid);
	}
	$shmid = shmop_open (GEOIP_SHM_KEY, "c", 0644, $size);
	shmop_write ($shmid, fread($fp, $size), 0);
	shmop_close ($shmid);
}

function _setup_segments($gi){
	$gi->databaseType = GEOIP_COUNTRY_EDITION;
	$gi->record_length = STANDARD_RECORD_LENGTH;
	if ($gi->flags & GEOIP_SHARED_MEMORY) {
		$offset = @shmop_size ($gi->shmid) - 3;
		for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
			$delim = @shmop_read ($gi->shmid, $offset, 3);
			$offset += 3;
			if ($delim == (chr(255).chr(255).chr(255))) {
				$gi->databaseType = ord(@shmop_read ($gi->shmid, $offset, 1));
				$offset++;

				if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
					$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
				} else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
					$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
			} else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)||
						 ($gi->databaseType == GEOIP_CITY_EDITION_REV1) 
						|| ($gi->databaseType == GEOIP_ORG_EDITION)
						|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
				|| ($gi->databaseType == GEOIP_ISP_EDITION)
				|| ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
				|| ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
				|| ($gi->databaseType == GEOIP_ASNUM_EDITION)){
					$gi->databaseSegments = 0;
					$buf = @shmop_read ($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
					for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++) {
						$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
					}
					if (($gi->databaseType == GEOIP_ORG_EDITION)
							|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
				|| ($gi->databaseType == GEOIP_ISP_EDITION)) {
						$gi->record_length = ORG_RECORD_LENGTH;
					}
				}
				break;
			} else {
				$offset -= 4;
			}
		}
		if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
			($gi->databaseType == GEOIP_PROXY_EDITION)||
			($gi->databaseType == GEOIP_NETSPEED_EDITION)) {
			$gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
		}
  } else {
	$filepos = ftell($gi->filehandle);
	fseek($gi->filehandle, -3, SEEK_END);
	for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
		$delim = fread($gi->filehandle,3);
		if ($delim == (chr(255).chr(255).chr(255))) {
		$gi->databaseType = ord(fread($gi->filehandle,1));
		if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
			$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
		}
		elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
			$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
		} elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
					|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1) 
					|| ($gi->databaseType == GEOIP_ORG_EDITION) 
					|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
			|| ($gi->databaseType == GEOIP_ISP_EDITION)
			|| ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
			|| ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
					|| ($gi->databaseType == GEOIP_ASNUM_EDITION)) {
			$gi->databaseSegments = 0;
			$buf = fread($gi->filehandle,SEGMENT_RECORD_LENGTH);
			for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
			$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
			}
		if (( $gi->databaseType == GEOIP_ORG_EDITION )
				|| ( $gi->databaseType == GEOIP_DOMAIN_EDITION )
				|| ( $gi->databaseType == GEOIP_ISP_EDITION ) ) {
			$gi->record_length = ORG_RECORD_LENGTH;
			}
		}
		break;
		} else {
			fseek($gi->filehandle, -4, SEEK_CUR);
		}
	}
		if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
			($gi->databaseType == GEOIP_PROXY_EDITION)||
			($gi->databaseType == GEOIP_NETSPEED_EDITION)){
			 $gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
		}
		fseek($gi->filehandle,$filepos,SEEK_SET);
	}
	return $gi;
}

function geoip_open($filename, $flags) {
	$gi = new GeoIP;
	$gi->flags = $flags;
	if ($gi->flags & GEOIP_SHARED_MEMORY) {
		$gi->shmid = @shmop_open (GEOIP_SHM_KEY, "a", 0, 0);
	} else {
		$gi->filehandle = fopen($filename,"rb") or die( "Can not open $filename\n" );
		if ($gi->flags & GEOIP_MEMORY_CACHE) {
			$s_array = fstat($gi->filehandle);
			$gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
		}
	}

	$gi = _setup_segments($gi);
	return $gi;
}

function geoip_close($gi) {
	if ($gi->flags & GEOIP_SHARED_MEMORY) {
		return true;
	}

	return fclose($gi->filehandle);
}

function geoip_country_id_by_name($gi, $name) {
	$addr = gethostbyname($name);
	if (!$addr || $addr == $name) {
		return false;
	}
	return geoip_country_id_by_addr($gi, $addr);
}

function geoip_country_code_by_name($gi, $name) {
	$country_id = geoip_country_id_by_name($gi,$name);
	if ($country_id !== false) {
		return $gi->GEOIP_COUNTRY_CODES[$country_id];
	}
	return false;
}

function geoip_country_name_by_name($gi, $name) {
	$country_id = geoip_country_id_by_name($gi,$name);
	if ($country_id !== false) {
		return $gi->GEOIP_COUNTRY_NAMES[$country_id];
	}
	return false;
}

function geoip_country_id_by_addr($gi, $addr) {
	$ipnum = ip2long($addr);
	return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
}

function geoip_country_code_by_addr($gi, $addr) {
	if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
		$record = geoip_record_by_addr($gi,$addr);
	if ( $record !== false ) {
		return $record->country_code;
	}
  } else {
	$country_id = geoip_country_id_by_addr($gi,$addr);
	if ($country_id !== false) {
		return $gi->GEOIP_COUNTRY_CODES[$country_id];
		}
	}
	return false;
}

function geoip_country_name_by_addr($gi, $addr) {
	if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
		$record = geoip_record_by_addr($gi,$addr);
		return $record->country_name;
	} else {
		$country_id = geoip_country_id_by_addr($gi,$addr);
		if ($country_id !== false) {
			return $gi->GEOIP_COUNTRY_NAMES[$country_id];
		}
	}
	return false;
}

function _geoip_seek_country($gi, $ipnum) {
  $offset = 0;
  for ($depth = 31; $depth >= 0; --$depth) {
	if ($gi->flags & GEOIP_MEMORY_CACHE) {
		$enc = mb_internal_encoding();
		mb_internal_encoding('ISO-8859-1'); 

		$buf = substr($gi->memory_buffer,
							2 * $gi->record_length * $offset,
							2 * $gi->record_length);

	  mb_internal_encoding($enc);
	} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
	  $buf = @shmop_read ($gi->shmid, 
							2 * $gi->record_length * $offset,
							2 * $gi->record_length );
		} else {
	  fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
		or die("fseek failed");
	  $buf = fread($gi->filehandle, 2 * $gi->record_length);
	}
	$x = array(0,0);
	for ($i = 0; $i < 2; ++$i) {
	  for ($j = 0; $j < $gi->record_length; ++$j) {
		$x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
	  }
	}
	if ($ipnum & (1 << $depth)) {
	  if ($x[1] >= $gi->databaseSegments) {
		return $x[1];
	  }
	  $offset = $x[1];
		} else {
	  if ($x[0] >= $gi->databaseSegments) {
		return $x[0];
	  }
	  $offset = $x[0];
	}
  }
  trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
  return false;
}

function _get_org($gi,$ipnum) {
  $seek_org = _geoip_seek_country($gi,$ipnum);
  if ($seek_org == $gi->databaseSegments) {
	return NULL;
  }
  $record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
  if ($gi->flags & GEOIP_SHARED_MEMORY) {
	$org_buf = @shmop_read ($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
	} else {
	fseek($gi->filehandle, $record_pointer, SEEK_SET);
	$org_buf = fread($gi->filehandle,MAX_ORG_RECORD_LENGTH);
  }
  $enc = mb_internal_encoding();
  mb_internal_encoding('ISO-8859-1'); 
  $org_buf = substr($org_buf, 0, strpos($org_buf, "\0"));
  mb_internal_encoding($enc);
  return $org_buf;
}

function geoip_org_by_addr ($gi,$addr) {
  if ($addr == NULL) {
	return 0;
  }
  $ipnum = ip2long($addr);
  return _get_org($gi, $ipnum);
}

function _get_region($gi,$ipnum) {
  if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
	$seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV0;
	if ($seek_region >= 1000){
	  $country_code = "US";
	  $region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65);
	} else {
			$country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
	  $region = "";
	}
  return array ($country_code,$region);
	}  else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
	$seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV1;
	//print $seek_region;
	if ($seek_region < US_OFFSET){
	  $country_code = "";
	  $region = "";  
		} else if ($seek_region < CANADA_OFFSET) {
	  $country_code = "US";
	  $region = chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65);
		} else if ($seek_region < WORLD_OFFSET) {
	  $country_code = "CA";
	  $region = chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65);
	} else {
			$country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
	  $region = "";
	}
  return array ($country_code,$region);
  }
}

function geoip_region_by_addr ($gi,$addr) {
  if ($addr == NULL) {
	return 0;
  }
  $ipnum = ip2long($addr);
  return _get_region($gi, $ipnum);
}

function getdnsattributes ($l,$ip){
  $r = new Net_DNS_Resolver();
  $r->nameservers = array("ws1.maxmind.com");
  $p = $r->search($l."." . $ip .".s.maxmind.com","TXT","IN");
  $str = is_object($p->answer[0])?$p->answer[0]->string():'';
  ereg("\"(.*)\"",$str,$regs);
  $str = $regs[1];
  return $str;
}

define("FULL_RECORD_LENGTH", 50);

require_once libfile('geo/ipregionvars', 'include');

class geoiprecord {
  var $country_code;
  var $country_code3;
  var $country_name;
  var $region;
  var $city;
  var $postal_code;
  var $latitude;
  var $longitude;
  var $area_code;
  var $dma_code;
  var $metro_code;
  var $continent_code;
}

class geoipdnsrecord {
  var $country_code;
  var $country_code3;
  var $country_name;
  var $region;
  var $regionname;
  var $city;
  var $postal_code;
  var $latitude;
  var $longitude;
  var $areacode;
  var $dmacode;
  var $isp;
  var $org;
  var $metrocode;
}

function getrecordwithdnsservice($str) {
  $record = new geoipdnsrecord;
  $keyvalue = split(";",$str);
  foreach ($keyvalue as $keyvalue2){
	list($key,$value) = split("=",$keyvalue2);
	if ($key == "co"){
	  $record->country_code = $value;
	}
	if ($key == "ci"){
	  $record->city = $value;
	}
	if ($key == "re"){
	  $record->region = $value;
	}
	if ($key == "ac"){
	  $record->areacode = $value;
	}
	if ($key == "dm" || $key == "me" ){
	  $record->dmacode   = $value;
	  $record->metrocode = $value;
	}
	if ($key == "is"){
	  $record->isp = $value;
	}
	if ($key == "or"){
	  $record->org = $value;
	}
	if ($key == "zi"){
	  $record->postal_code = $value;
	}
	if ($key == "la"){
	  $record->latitude = $value;
	}
	if ($key == "lo"){
	  $record->longitude = $value;
	}
  }
  $number = $GLOBALS['GEOIP_COUNTRY_CODE_TO_NUMBER'][$record->country_code];
  $record->country_code3 = $GLOBALS['GEOIP_COUNTRY_CODES3'][$number];
  $record->country_name = $GLOBALS['GEOIP_COUNTRY_NAMES'][$number];
  if ($record->region != "") {
	if (($record->country_code == "US") || ($record->country_code == "CA")){
	  $record->regionname = $GLOBALS['ISO'][$record->country_code][$record->region];
	} else {
	  $record->regionname = $GLOBALS['FIPS'][$record->country_code][$record->region];
	}
  }
  return $record;
}

function _get_record($gi,$ipnum) {
  $seek_country = _geoip_seek_country($gi,$ipnum);
  if ($seek_country == $gi->databaseSegments) {
	return NULL;
  }
  
  $enc = mb_internal_encoding();
  mb_internal_encoding('ISO-8859-1'); 

  $record_pointer = $seek_country + (2 * $gi->record_length - 1) * $gi->databaseSegments;
  
  if ($gi->flags & GEOIP_MEMORY_CACHE) {
	$record_buf = substr($gi->memory_buffer,$record_pointer,FULL_RECORD_LENGTH);
  } elseif ($gi->flags & GEOIP_SHARED_MEMORY){
	$record_buf = @shmop_read($gi->shmid,$record_pointer,FULL_RECORD_LENGTH);
  } else {
	fseek($gi->filehandle, $record_pointer, SEEK_SET);
	$record_buf = fread($gi->filehandle,FULL_RECORD_LENGTH);
  }
  $record = new geoiprecord;
  $record_buf_pos = 0;
  $char = ord(substr($record_buf,$record_buf_pos,1));
	$record->country_code = $gi->GEOIP_COUNTRY_CODES[$char];
	$record->country_code3 = $gi->GEOIP_COUNTRY_CODES3[$char];
	$record->country_name = $gi->GEOIP_COUNTRY_NAMES[$char];
  $record->continent_code = $gi->GEOIP_CONTINENT_CODES[$char];
  $record_buf_pos++;
  $str_length = 0;
	// Get region
  $char = ord(substr($record_buf,$record_buf_pos+$str_length,1));
  while ($char != 0){
	$str_length++;
	$char = ord(substr($record_buf,$record_buf_pos+$str_length,1));
  }
  if ($str_length > 0){
	$record->region = substr($record_buf,$record_buf_pos,$str_length);
  }
  $record_buf_pos += $str_length + 1;
  $str_length = 0;
	// Get city
  $char = ord(substr($record_buf,$record_buf_pos+$str_length,1));
  while ($char != 0){
	$str_length++;
	$char = ord(substr($record_buf,$record_buf_pos+$str_length,1));
  }
  if ($str_length > 0){
	$record->city = substr($record_buf,$record_buf_pos,$str_length);
  }
  $record_buf_pos += $str_length + 1;
  $str_length = 0;
	// Get postal code
  $char = ord(substr($record_buf,$record_buf_pos+$str_length,1));
  while ($char != 0){
	$str_length++;
	$char = ord(substr($record_buf,$record_buf_pos+$str_length,1));
  }
  if ($str_length > 0){
	$record->postal_code = substr($record_buf,$record_buf_pos,$str_length);
  }
  $record_buf_pos += $str_length + 1;
  $str_length = 0;
	// Get latitude and longitude
  $latitude = 0;
  $longitude = 0;
  for ($j = 0;$j < 3; ++$j){
	$char = ord(substr($record_buf,$record_buf_pos++,1));
	$latitude += ($char << ($j * 8));
  }
  $record->latitude = ($latitude/10000) - 180;
  for ($j = 0;$j < 3; ++$j){
	$char = ord(substr($record_buf,$record_buf_pos++,1));
	$longitude += ($char << ($j * 8));
  }
  $record->longitude = ($longitude/10000) - 180;
  if (GEOIP_CITY_EDITION_REV1 == $gi->databaseType){
	$metroarea_combo = 0;
	if ($record->country_code == "US"){
	  for ($j = 0;$j < 3;++$j){
		$char = ord(substr($record_buf,$record_buf_pos++,1));
		$metroarea_combo += ($char << ($j * 8));
	  }
	  $record->metro_code = $record->dma_code = floor($metroarea_combo/1000);
	  $record->area_code = $metroarea_combo%1000;
	}
  }
  mb_internal_encoding($enc);
  return $record;
}

function GeoIP_record_by_addr ($gi,$addr){
  if ($addr == NULL){
	 return 0;
  }
  $ipnum = ip2long($addr);
  return _get_record($gi, $ipnum);
}


?>
